package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strconv"
)

func main() {
	//open 打开一个文件用于读取，如果操作成功，返回的文件对象的方法可用于读取数据，对应的文件描述符具有O_RDONLY模式，如果出错，错误底层类型是PathError
	//file, err := os.Open("E:\\code\\go\\demo34\\Test.txt")
	file, err := os.Open("E:/code/go/demo34/Test.txt")

	if err != nil {
		println("文件打开出错", err)
	}

	//没有文件，输出文件
	fmt.Printf("文件=%v\n", file)

	//关闭文件
	err = file.Close()
	if err != nil {
		println("文件关闭失败")
	}

	//我们无法用file结构体无法对文件内部进行操作，因此我们要引入io操作（流操作） i输入流 o输出流

	//IO1：读取文件的内容并显示在终端，使用ioutil一次性将整个文件读入内存中，这种方法适用于文件不大的情况，相关方法和函数(ioutil.ReadFile)
	//读取文件
	content, err := ioutil.ReadFile("E:\\code\\go\\demo34\\Test.txt") //返回内容[]byte,err    这里不需要打开文件和关闭文件是因为ioutil.ReadFile()已经封装好了
	if err != nil {
		fmt.Println("文件读取失败", err)
	}
	//如果读取成功，将内容显示在终端即可
	fmt.Printf("%v\n", string(content)) //直接输出content[116 104 105 115 32 105 115 32 84 101 115 116 32 102 105 108 101] 拆成ascll；如果需要字符串可以 string(content)

	//IO2:读取文件的内容并且显示在终端（带缓冲的方式(一次读取4096)），适合读取比较大的文件，使用os.Open,file,Close,bufio,NewReader(),reader,ReadString函数和方法（对比ioutil.ReadFile()没有去封装）

	//打开文件
	file1, err1 := os.Open("E:\\code\\go\\demo34\\Test.txt")
	if err1 != nil {
		fmt.Println("文件打开失败", err1)
	}
	//当函数退出时，让file关闭，防止内存泄露
	defer file1.Close() //最后执行这个关闭操作

	//创建流
	reader := bufio.NewReader(file1)
	//读取方法
	for {

		readString, err2 := reader.ReadString('\n') //读到换行符结束  主要这里是一个字符，只能用单引号不能用双引号
		if err2 == io.EOF {                         //读到文件末尾会返回这个io.eof
			break
		}
		fmt.Printf("%v", string(readString))
	}

	fmt.Printf("文件读取成功并成功关闭文件")

	//写入文件 我们有时候要将数据写入至文件当中
	//func OpenFile(name string,flag int,perm FileMode)(file *File,err error)
	//三个参数1.要打开的文件路径 2文件打开的模式(可以利用|符号进行组合) 3.权限控制(linux/unix系统下才生效，windows下设置无效)
	//打开文件模式 os.O_RDONLY：只读模式打开文件。
	//os.O_WRONLY：只写模式打开文件。
	//os.O_RDWR：读写模式打开文件。
	//os.O_APPEND：在文件末尾追加数据，而不是覆盖已存在的内容。
	//os.O_CREATE：如果文件不存在，创建一个新文件。
	//os.O_TRUNC：如果文件已存在，将其长度截断为 0。
	//os.O_EXCL：与 os.O_CREATE 一起使用时，要求创建的文件必须不存在。
	//os.O_SYNC：在每次写入操作完成后强制刷新文件的内容到磁盘。
	//os.O_NONBLOCK 或 os.O_NDELAY：以非阻塞模式打开文件，如果文件无法立即打开，不会阻塞进程。
	file2, err := os.OpenFile("E:\\code\\go\\demo34\\Test.txt", os.O_APPEND, 0666)
	defer file2.Close()
	if err != nil {
		fmt.Println("文件打开失败")
	}

	//写入文件操作：-----》IO流--------》缓冲输出流(带缓冲区)
	writer := bufio.NewWriter(file2)
	for i := 10; i < 20; i++ {
		writer.WriteString("你好曾宇杰" + strconv.Itoa(i) + "\n")
	}
	writer.Flush() //将缓冲区的数据刷新至文件中

	//文件复制
	//一边读取一边写入

	//定义源文件
	filePath := "E:\\code\\go\\demo34\\Test.txt"
	//定义目标文件
	file2Path := "E:\\code\\go\\demo34\\Test1.txt"

	//对文件进行读取
	readFile, err := ioutil.ReadFile(filePath)
	if err != nil {
		fmt.Println("源文件读取失败")
	}
	//写出
	err = ioutil.WriteFile(file2Path, readFile, 0666)
	if err != nil {
		fmt.Println("写出失败", err)
	}
	fmt.Println("复制成功")
}
